package com.schoolvisitors.service;

import com.schoolvisitors.dto.UpdateUserDtoByManage;
import com.schoolvisitors.dto.UserInfoDto;
import com.schoolvisitors.dto.UserRegisterDto;
import com.schoolvisitors.entity.RegisterToken;
import com.schoolvisitors.entity.User;
import com.schoolvisitors.enums.GenderEnum;
import com.schoolvisitors.enums.UserStatusEnum;
import com.schoolvisitors.exception.BusinessException;
import com.schoolvisitors.exception.ServiceException;
import com.schoolvisitors.repository.RegisterTokenRepository;
import com.schoolvisitors.repository.UserRepository;
import com.schoolvisitors.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.Objects;

@Slf4j
@Service
public class UserService {
    private final UserRepository userRepository;
    private final SystemConfigService systemConfigService;
    private final RegisterTokenRepository registerTokenRepository;

    public UserService(UserRepository userRepository, SystemConfigService systemConfigService, RegisterTokenRepository registerTokenRepository) {
        this.userRepository = userRepository;
        this.systemConfigService = systemConfigService;
        this.registerTokenRepository = registerTokenRepository;
    }

    public UserInfoDto getUserInfo(Long userId) {
        log.info("获取用户信息: {}", userId);

        User user = userRepository.findById(userId).orElseThrow(() -> new ServiceException(ResultCode.USER_NOT_FOUND));

        UserInfoDto userInfoDto = new UserInfoDto();
        userInfoDto.setGender(user.getGender());
//        userInfoDto.setUsername(user.getRealName());
        userInfoDto.setNickname(user.getNickname());
        userInfoDto.setIdNumber(user.getIdNumber());
        userInfoDto.setPhone(user.getPhone());
        userInfoDto.setPoints(Math.toIntExact(user.getPoints()));
        return userInfoDto;
    }

    public User findByWeChatUserId(String weChatUserId) {
        return userRepository.findByWechatUserId(weChatUserId);
    }
    public User findById(Long userId){
        return userRepository.findById(userId).orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));
    }

    // 用户注册
    @Transactional(rollbackFor = Exception.class)
    public void register(UserRegisterDto userRegisterDto) {
        RegisterToken registerToken = registerTokenRepository.findByToken(userRegisterDto.getToken());
        if (registerToken == null){
            throw new BusinessException(ResultCode.REGISTER_VERIFY_FAIL);
        }
        String weChatUserId = registerToken.getWechatUserId();
        if (userRepository.existsByPhone(userRegisterDto.getPhone())) {
            throw new BusinessException(ResultCode.PHONE_IS_USE);
        }
        if (userRepository.existsByIdNumber(userRegisterDto.getIdNumber())) {
            throw new BusinessException(ResultCode.ID_NUMBER_IS_USE);
        }

        // 获取默认积分
        Integer defaultPoint = systemConfigService.getIntSystemConfigToInteger("defaultPoint");

        User user = new User();
        user.setWechatUserId(weChatUserId);
        user.setNickname(userRegisterDto.getNickname());
        user.setPassword("");
        user.setRealName(userRegisterDto.getRealName());
        user.setGender(userRegisterDto.getGender());
        user.setIdNumber(userRegisterDto.getIdNumber());
        user.setPhone(userRegisterDto.getPhone());
        user.setPoints(Long.valueOf(defaultPoint));
        user.setReservationPermission(false);
        user.setIsActive(true);
        user.setStatus(UserStatusEnum.PENDING_APPROVAL);
        user.setCreateAt(LocalDateTime.now());
        user.setUpdateAt(LocalDateTime.now());
        user.setPosition(userRegisterDto.getPosition());
//        user.setIsActive(false);

        userRepository.save(user);
        registerTokenRepository.delete(registerToken);
    }

    // 用户注册
//    @Transactional(rollbackFor = Exception.class)
//    public void registerByAdmin(UserRegisterDto userRegisterDto) {
//        String weChatUserId = registerToken.getWechatUserId();
//        if (userRepository.existsByPhone(userRegisterDto.getPhone())) {
//            throw new BusinessException(ResultCode.PHONE_IS_USE);
//        }
//        if (userRepository.existsByIdNumber(userRegisterDto.getIdNumber())) {
//            throw new BusinessException(ResultCode.ID_NUMBER_IS_USE);
//        }
//
//        // 获取默认积分
//        Integer defaultPoint = systemConfigService.getIntSystemConfigToInteger("defaultPoint");
//
//        User user = new User();
//        user.setWechatUserId(weChatUserId);
//        user.setNickname(userRegisterDto.getNickname());
//        user.setPassword("");
//        user.setRealName(userRegisterDto.getRealName());
//        user.setGender(userRegisterDto.getGender());
//        user.setIdNumber(userRegisterDto.getIdNumber());
//        user.setPhone(userRegisterDto.getPhone());
//        user.setPoints(Long.valueOf(defaultPoint));
//        user.setReservationPermission(false);
//        user.setIsActive(true);
//        user.setStatus(UserStatusEnum.PENDING_APPROVAL);
//        user.setCreateAt(LocalDateTime.now());
//        user.setUpdateAt(LocalDateTime.now());
//        user.setPosition(userRegisterDto.getPosition());
////        user.setIsActive(false);
//
//        userRepository.save(user);
//        registerTokenRepository.delete(registerToken);
//    }

    public Page<User> findUsers(int page, int size, String search) {
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("id").descending());

        if (StringUtils.hasText(search)) {
            return userRepository.findByRealNameContaining(search, pageable);
        } else {
            return userRepository.findAll(pageable);
        }
    }

    // 添加积分
    @Transactional(rollbackFor = Exception.class)
    public void addPoint(Long userId, Long point) {
        User user = userRepository.findByIdWithLock(userId).orElseThrow(() -> new ServiceException(ResultCode.USER_NOT_FOUND));
        log.info("用户添加积分 {} 原始积分{} 新增{}", userId, user.getPoints(), point);
        user.setPoints(user.getPoints() + point);
        log.info("结果: {}", user.getPoints());
        userRepository.save(user);
    }


    @Transactional(rollbackFor = Exception.class)
    public void subtractPoint(Long userId, Long point) {
        User user = userRepository.findByIdWithLock(userId).orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));
        if (user.getPoints() < point) {
            throw new BusinessException(ResultCode.USER_INSUFFICIENT_POINTS);
        }
        user.setPoints(user.getPoints() - point);
        userRepository.saveAndFlush(user);
    }


    public Page<User> findUsersByNotReview(int page, int size) {
        Pageable pageable = PageRequest.of(page - 1, size, Sort.by("id").descending());
        return userRepository.findByStatus(UserStatusEnum.PENDING_APPROVAL, pageable);
    }

    // 设置用户审核权限
    @Transactional(rollbackFor = Exception.class)
    public void reviewReservationPermission(Long userId, boolean reservationPermission) {
        User user = userRepository.findByIdWithLock(userId).orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));
        if (!user.getStatus().equals(UserStatusEnum.PENDING_APPROVAL)) {
            throw new BusinessException(ResultCode.USER_IS_REVIEWED);
        }
        user.setStatus(UserStatusEnum.ACTIVE);
        user.setReservationPermission(reservationPermission);
        userRepository.save(user);
    }


    public User updateUser(UpdateUserDtoByManage request) {
        Long id = request.getId();
        User user = userRepository.findById(request.getId()).orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));

        // 校验手机号和身份证号（排除当前记录）
        if (userRepository.existsByPhoneAndIdNot(request.getPhone(), id)) {
            throw new BusinessException(ResultCode.PHONE_IS_USE);
        }
        if (userRepository.existsByIdNumberAndIdNot(request.getIdNumber(), id)) {
            throw new BusinessException(ResultCode.ID_NUMBER_IS_USE);
        }

        // 更新字段
        user.setNickname(request.getNickname());
        user.setRealName(request.getRealName());
        user.setPhone(request.getPhone());
        user.setIdNumber(request.getIdNumber());
        user.setPosition(request.getPosition());
        user.setGender(Objects.equals(request.getGender(), "男") ? GenderEnum.MALE : GenderEnum.FEMALE);

        user.setReservationPermission(request.getReservationPermission());
        user.setUpdateAt(LocalDateTime.now());
        return userRepository.save(user);
    }

    public void deleteUser(Long id) {
        User user = userRepository.findById(id).orElseThrow(() -> new BusinessException(ResultCode.USER_NOT_FOUND));

    }
}
